package freedom;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 三消问题
 *
 * 输入
 * [[A1,B1,B1,C1,A1],
 * [C1,B1,C1,A1,B1],
 * [C1,A1,C1,C1,B1],
 * [A1,A1,B1,C1,A1],
 * [A1,B1,A1,A1,B1]]
 */
public class F002_三消问题 {

    public static void main(String[] args) {

        String[][] arr = {
                {"A1","B1","B1","C1","A1"},
                {"C1","B1","C1","A1","B1"},
                {"C1","A1","C1","C1","B1"},
                {"A1","A1","B1","C1","A1"},
                {"A1","B1","A1","A1","B1"}};

        String[][] forbiddenArr = {{"2","0"}};
        Set<String> forbidden = Arrays.stream(forbiddenArr).map(strings -> strings[0] + "-" + strings[1]).collect(Collectors.toSet());

        F002_三消问题 func = new F002_三消问题();
        String[] strings = func.nextBest(arr, forbidden);
        System.out.println(Arrays.stream(strings).collect(Collectors.joining(",")));

    }

    public String[] nextBest(String[][] arr, Set<String> forbiddenSet){

        Set<String> sets = new HashSet<>();

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                sets.add(arr[i][j]);
            }
        }

        List<Object[]> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                if(forbiddenSet.contains(i+"-"+j)){
                    continue;
                }

                String self = arr[i][j];

                //改变自身的值，计算能得到的最大值
                for (String set : sets) {
                    if(set.equals(self)){
                        continue;
                    }

                    List<Integer[]> blockList = new ArrayList<>();
                    blockList.add(new Integer[]{i,j});

                    //左上
                    Integer leftTopSameNum = countLeftTopSameNum(set, i, j, arr, 0, forbiddenSet);
                    if(leftTopSameNum>=2){
                        int temp1 = i, temp2 = j;
                        for (Integer integer = 0; integer < leftTopSameNum; integer++) {
                            blockList.add(new Integer[]{--temp1, --temp2});
                        }
                    }else{
                        leftTopSameNum = 0;
                    }
                    //左边
                    Integer leftSameNum = countLeftSameNum(set, i, j, arr, 0, forbiddenSet);
                    if(leftSameNum>=2){
                        int temp1 = i, temp2 = j;
                        for (Integer integer = 0; integer < leftSameNum; integer++) {
                            blockList.add(new Integer[]{temp1, --temp2});
                        }
                    }else{
                        leftSameNum = 0;
                    }
                    //左下
                    Integer leftBottomSameNum = countLeftBottomSameNum(set, i, j, arr, 0, forbiddenSet);
                    if(leftBottomSameNum>=2){
                        int temp1 = i, temp2 = j;
                        for (Integer integer = 0; integer < leftBottomSameNum; integer++) {
                            blockList.add(new Integer[]{++temp1, --temp2});
                        }
                    }else{
                        leftBottomSameNum = 0;
                    }
                    //上边
                    Integer topSameNum = countTopSameNum(set, i, j, arr, 0, forbiddenSet);
                    if(topSameNum>=2){
                        int temp1 = i, temp2 = j;
                        for (Integer integer = 0; integer < topSameNum; integer++) {
                            blockList.add(new Integer[]{--temp1, temp2});
                        }
                    }else{
                        topSameNum = 0;
                    }
                    //下边
                    Integer bottomSameNum = countBottomSameNum(set, i, j, arr, 0, forbiddenSet);
                    if(bottomSameNum>=2){
                        int temp1 = i, temp2 = j;
                        for (Integer integer = 0; integer < bottomSameNum; integer++) {
                            blockList.add(new Integer[]{++temp1, temp2});
                        }
                    }else{
                        bottomSameNum = 0;
                    }
                    //右上
                    Integer rightTopSameNum = countRightTopSameNum(set, i, j, arr, 0, forbiddenSet);
                    if(rightTopSameNum>=2){
                        int temp1 = i, temp2 = j;
                        for (Integer integer = 0; integer < rightTopSameNum; integer++) {
                            blockList.add(new Integer[]{--temp1, ++temp2});
                        }
                    }else{
                        rightTopSameNum = 0;
                    }
                    //右边
                    Integer rightSameNum = countRightSameNum(set, i, j, arr, 0, forbiddenSet);
                    if(rightSameNum>=2){
                        int temp1 = i, temp2 = j;
                        for (Integer integer = 0; integer < rightSameNum; integer++) {
                            blockList.add(new Integer[]{temp1, ++temp2});
                        }
                    }else{
                        rightSameNum = 0;
                    }
                    //右下
                    Integer rightBottomSameNum = countRightBottomSameNum(set, i, j, arr, 0, forbiddenSet);
                    if(rightBottomSameNum>=2){
                        int temp1 = i, temp2 = j;
                        for (Integer integer = 0; integer < rightBottomSameNum; integer++) {
                            blockList.add(new Integer[]{++temp1, ++temp2});
                        }
                    }else{
                        rightBottomSameNum = 0;
                    }

                    int count = leftTopSameNum
                            +leftSameNum
                            +leftBottomSameNum
                            +topSameNum
                            +bottomSameNum
                            +rightTopSameNum
                            +rightSameNum
                            +rightBottomSameNum
                            +1
                            ;

                    if(count >= 3){


                        Object[] arrs = new Object[6];
                        arrs[0] = String.valueOf(count);
                        arrs[1] = String.valueOf(i);
                        arrs[2] = String.valueOf(j);
                        arrs[3] = self;
                        arrs[4] = set;
                        arrs[5] = blockList;
                        list.add(arrs);

                    }
                }

            }

        }

        list.sort((o1,o2) -> Integer.valueOf(
                String.valueOf(o2[0])) - Integer.valueOf(String.valueOf(o1[0])));

        return getMaxCombo(list);

    }

    private String[] getMaxCombo(List<Object[]> list) {

        int maxCount = 0;
        String arr[] = new String[2];
        for (int i = 0; i < list.size()-1; i++) {
            //先取分数最大的
            Object[] strings = list.get(i);
            int count = Integer.parseInt((String) strings[0]);

            String lat = (String) strings[1];
            String lon = (String) strings[2];
            String self = (String) strings[3];
            String target = (String) strings[4];
            List<Integer[]> blockList = (List<Integer[]>) strings[5];
            Set<String> set = blockList.stream().map(integers -> integers[0] + "-" + integers[1]).collect(Collectors.toSet());
            //找到该对象能匹配的最大值
            for (int j = i+1; j < list.size(); j++) {
                Object[] s2 = list.get(j);
                int s2Count = Integer.parseInt((String) s2[0]);

                String s2Lat = (String) s2[1];
                String s2Lon = (String) s2[2];
                Object s2Self = s2[3];
                Object s2Target = s2[4];
                if(!self.equals(s2Target) || !target.equals(s2Self)){
                    continue;
                }
                //去掉重复区域
                List<Integer[]> s2BlockList = (List<Integer[]>) s2[5];
                Set<String> s2Set = s2BlockList.stream().map(integers -> integers[0] + "-" + integers[1]).collect(Collectors.toSet());
                int total = set.size() + s2Set.size();

                HashSet<Object> hashSet = new HashSet<>();
                hashSet.addAll(set);
                hashSet.addAll(s2Set);
                if(total != hashSet.size()){
                    continue;
                }

                if(total > maxCount){
                    maxCount = total;
                    arr[0] = lat+"-"+lon;
                    arr[1] = s2Lat+"-"+s2Lon;
                }

            }
        }

        return arr;

    }

    /**
     * 左上相同数量
     * @return
     */
    public Integer countLeftTopSameNum(String origin, int i, int j, String[][] arr,  Integer count, Set forbiddenSet){
        i = i -1; j= j-1;

        if(i<0 || j<0){
            return count;
        }
        boolean ifForbidden = forbiddenSet.contains(i + "-" + j);
        if(ifForbidden){
            return count;
        }
        String target = arr[i][j];
        if(target.equals(origin)){
            count++;
        }else{
            return count;
        }
        return countLeftTopSameNum(origin, i, j,arr,count, forbiddenSet);
    }
    /**
     * 左边相同数量
     * @return
     */
    public Integer countLeftSameNum(String origin, int i, int j, String[][] arr,   Integer count, Set forbiddenSet){
        j = j-1;
        if(j<0){
            return count;
        }
        boolean ifForbidden = forbiddenSet.contains(i + "-" + j);
        if(ifForbidden){
            return count;
        }
        String target = arr[i][j];
        if(target.equals(origin)){
            count++;
        }else{
            return count;
        }
        return countLeftSameNum(origin, i, j,arr,count, forbiddenSet);
    }

    /**
     * 左下相同数量
     * @return
     */
    public Integer countLeftBottomSameNum(String origin, int i, int j, String[][] arr,  Integer count, Set forbiddenSet){
        i=i+1;j=j-1;
        if(i >= arr.length || j<0){
            return count;
        }
        boolean ifForbidden = forbiddenSet.contains(i + "-" + j);
        if(ifForbidden){
            return count;
        }
        String target = arr[i][j];
        if(target.equals(origin)){
            count++;
        }else{
            return count;
        }
        return countLeftBottomSameNum(origin, i, j,arr,count, forbiddenSet);
    }
    /**
     * 上方相同数量
     * @return
     */
    public Integer countTopSameNum(String origin, int i, int j, String[][] arr,  Integer count, Set forbiddenSet){
        i=i-1;
        if(i<0){
            return count;
        }
        boolean ifForbidden = forbiddenSet.contains(i + "-" + j);
        if(ifForbidden){
            return count;
        }
        String target = arr[i][j];
        if(target.equals(origin)){
            count++;
        }else{
            return count;
        }
        return countTopSameNum(origin, i, j,arr,count, forbiddenSet);
    }
    /**
     * 下方相同数量
     * @return
     */
    public Integer countBottomSameNum(String origin, int i, int j, String[][] arr,  Integer count, Set forbiddenSet){
        i=i+1;
        if(i >= arr.length){
            return count;
        }
        boolean ifForbidden = forbiddenSet.contains(i + "-" + j);
        if(ifForbidden){
            return count;
        }
        String target = arr[i][j];
        if(target.equals(origin)){
            count++;
        }else{
            return count;
        }
        return countBottomSameNum(origin, i, j,arr,count, forbiddenSet);
    }

    /**
     * 右上方相同数量
     * @return
     */
    public Integer countRightTopSameNum(String origin, int i, int j, String[][] arr,  Integer count, Set forbiddenSet){
        i=i-1;j=j+1;
        if(i<0 || j >= arr[i].length){
            return count;
        }
        
        boolean ifForbidden = forbiddenSet.contains(i + "-" + j);
        if(ifForbidden){
            return count;
        }
        String target = arr[i][j];
        if(target.equals(origin)){
            count++;
        }else{
            return count;
        }
        return countRightTopSameNum(origin, i, j,arr,count, forbiddenSet);
    }

    /**
     * 右方相同数量
     * @return
     */
    public Integer countRightSameNum(String origin, int i, int j, String[][] arr,  Integer count, Set forbiddenSet){
        j=j+1;
        if( j >= arr[i].length){
            return count;
        }
        boolean ifForbidden = forbiddenSet.contains(i + "-" + j);
        if(ifForbidden){
            return count;
        }
        String target = arr[i][j];
        if(target.equals(origin)){
            count++;
        }else{
            return count;
        }
        return countRightSameNum(origin, i, j,arr,count, forbiddenSet);
    }


    /**
     * 右下方相同数量
     * @return
     */
    public Integer countRightBottomSameNum(String origin, int i, int j, String[][] arr,  Integer count, Set forbiddenSet){
        i=i+1;j=j+1;
        if(i>=arr.length || j>= arr[i].length){
            return count;
        }
        boolean ifForbidden = forbiddenSet.contains(i + "-" + j);
        if(ifForbidden){
            return count;
        }
        String target = arr[i][j];
        if(target.equals(origin)){
            count++;
        }else{
            return count;
        }
        return countRightBottomSameNum(origin, i, j,arr,count, forbiddenSet);
    }

}
